package edu.fiu.cis.selfhealingdisk;

import java.util.HashMap;
import java.util.LinkedList;

/**
 * @author vanvorst
 *
 */
public abstract class ParityModel {
	protected final IOTrace originalTrace;
	protected final DiskLayout originalLayout;
	protected IOTrace transformedTrace=new IOTrace();
	protected DiskLayout transformedLayout=null;
	
	protected LinkedList<IORequest> pendingInterruptions = null;
	
	/**
	 * @param config
	 */
	public final static ParityModel createParityModel(final Configuration config, IOTrace trace) {
		switch(config.getParityFormat()) {
		
		case FRAGMENTED:
			ParityModel pm = null;
			if (config.getMemoryManagement()) {
				pm = new BufferedParityModel(trace, new DiskLayout(config, trace.getMaxBlockNumber()),config.getMemorySizeInBlocks(), 50 , config.getMaxTimeInMemory());
			} else {
				pm = new FragmentedParityModel(trace, new DiskLayout(config, trace.getMaxBlockNumber()));
			}
			return pm;
		case LOG:
			return new LogParityModel(trace, new DiskLayout(config, trace.getMaxBlockNumber()));
		case NOPARITY:
			return new NoParity(trace, new DiskLayout(config, trace.getMaxBlockNumber()));
		default:
			throw new RuntimeException("Unknown partity format enum '"+config.getParityFormat()+"'");
		}
	}

	/**
	 * @param originalTrace
	 * @param originalLayout
	 */
	protected ParityModel(final IOTrace originalTrace, DiskLayout originalLayout) {
		this.originalTrace=originalTrace;
		this.originalLayout=originalLayout;
	}
	
	/**
	 *  This is called by the DiskSimInterface to get events from the parity model. 
	 *  When ever this is called, zero or more IORequest that had previously been
	 *  sent to DiskSim may have their service time's updated to indicate that they
	 *  have been serviced.
	 *  
	 *  If an event of type STALL is returned, that DiskSimInterface will advanced time 
	 *  until an event from DiskSim before calling nextEvent again. If DONE is returned,
	 *  the simulation will stop after all IORequests are serviced. 
	 * 
	 * @param currentTime the current time
	 * 
	 * @return the event
	 */
	public abstract Event nextEvent(long currentTime);
	
	/**
	 * @return
	 */
	public final IOTrace getTransformedTrace() {
		return this.transformedTrace;
	}
	
	/**
	 * @return
	 */
	public final DiskLayout getTransformedLayout() {
		return this.transformedLayout;
	}
	
	/**
	 * This list is used to share the interruption between the SimulationExecutive and the ParityModel
	 * @param iorl
	 */
	public final void setInterruptions(LinkedList<IORequest> iorl) {
		this.pendingInterruptions = iorl;
	}
	
	
	public HashMap<String,String> getStats() {
		return new HashMap<String,String>();
	}
	
}
